package com.mar.quarkus.jwk;

import org.jose4j.jwk.JsonWebKey;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jwk.RsaJwkGenerator;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.MalformedClaimException;
import org.jose4j.lang.JoseException;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

/**
 * Description: 生成JWK .<br>
 *
 * @author 孟祥元
 * @Date 2020/7/27 16:47
 */
public class MakeJwk {
    public static String iss = "Issuser";
    public static String aud = "Audience";
    public static String sub = "Subject";
    public static int exp = 10;

    public static void main(String[] args) throws JoseException, MalformedClaimException {
        RsaJsonWebKey jwk = null;
        try {
            /* 生成RSA密钥对，用于签名与验证JWT */
            jwk = RsaJwkGenerator.generateJwk(2048);
        } catch (Exception e) {
            System.out.println("Generate JWK Failed! " + e);
            System.exit(1);
        }
        jwk.setAlgorithm(AlgorithmIdentifiers.RSA_USING_SHA256);

        System.out.println("\nJWK Private: ".concat(jwk.toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE)));
        System.err.println("\nJWK Public: ".concat(jwk.toJson(JsonWebKey.OutputControlLevel.PUBLIC_ONLY)));

        JwtClaims claims = new JwtClaims();
        claims.setIssuer("Issuer");  // who creates the token and signs it
        claims.setAudience("Audience"); // to whom the token is intended to be sent
        claims.setExpirationTimeMinutesInTheFuture(10); // time when the token will expire (10 minutes from now)
        claims.setGeneratedJwtId(); // a unique identifier for the token
        claims.setIssuedAtToNow();  // when the token was issued/created (now)
        claims.setNotBeforeMinutesInThePast(2); // time before which the token is not yet valid (2 minutes ago)
        claims.setSubject("subject"); // the subject/principal is whom the token is about
        claims.setClaim("email", "mail@example.com"); // additional claims/attributes about the subject can be added
        List<String> groups = Arrays.asList("group-one", "other-group", "group-three");
        claims.setStringListClaim("groups", groups); // multi-valued claims work too and will end up as a JSON array

        JsonWebSignature jws = new JsonWebSignature();

        // The payload of the JWS is JSON content of the JWT Claims
        jws.setPayload(claims.toJson());

        // The JWT is signed using the private key
        jws.setKey(jwk.getPrivateKey());

        // Set the Key ID (kid) header because it's just the polite thing to do.
        // We only have one key in this example but a using a Key ID helps
        // facilitate a smooth key rollover process
        jws.setKeyIdHeaderValue("CZ5XIPTwx7JiwqVrCR5lCbF0CLAKHBEs1DA4AP8NpQ");

        // Set the signature algorithm on the JWT/JWS that will integrity protect the claims
        jws.setAlgorithmHeaderValue(jwk.getAlgorithm());

        // 生成JWT 令牌
        // Sign the JWS and produce the compact serialization or the complete JWT/JWS
        // representation, which is a string consisting of three dot ('.') separated
        // base64url-encoded parts in the form Header.Payload.Signature
        // If you wanted to encrypt it, you can simply set this jwt as the payload
        // of a JsonWebEncryption object and set the cty (Content Type) header to "jwt".
        String jwt = jws.getCompactSerialization();

        long expirationTime = claims.getExpirationTime().getValueInMillis();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.SIMPLIFIED_CHINESE);
        String msg = String.format("JWT expired at (%d -> %s)", expirationTime, dateFormat.format(expirationTime));

        // 打印JWT 令牌过期时间
        System.out.println(msg);
        // 打印JWT 令牌
        System.out.println(jwt);
    }
}
